#include <ConfigInit.h>
/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-07-03     ThinkPad       the first version
 */
#include <rtthread.h>
#include <rtdevice.h>
#include "drv_common.h"
#include <dfs_posix.h>
#include <../utils/cJSON.h>
#include <../board/board_adc_poll.h>
#include <ComApp2.h>
#include <ComApp3.h>
#include <ComApp4.h>
#include <ComApp5.h>
#include <../board/board_relay.h>


static rt_uint8_t s_buf[1024] = {0};


static int s_saveSD = 0;
static int s_oldSaveSD = 0;
static rt_uint8_t g_timeStamp[7] = {0};

static int s_switch2 = 0;
static int s_switch3 = 0;
static int s_switch4 = 0;
static int s_switch5 = 0;
static int s_nPeriod = 20;

static int s_isNewFile = 1;
static rt_uint8_t s_localStamp[7] = {0};

extern rt_device_t serial1;


void setTimeStamp(void* src)
{
    memcpy(g_timeStamp, src, 7);
}

static void getTimeStamp(rt_uint8_t period)
{
    if (s_isNewFile)
    {
        memcpy(s_localStamp, g_timeStamp, 7);
        s_isNewFile = 0;
        return;
    }
    else
    {
        s_localStamp[6] += period/10;
        if (s_localStamp[6] > 99)
        {
            s_localStamp[6] -= 100;     // ms
            s_localStamp[5] += 1;

            if (s_localStamp[5] > 59)   // s
            {
                s_localStamp[5] -= 60;
                s_localStamp[4] += 1;
            }

            if (s_localStamp[4] > 59) // min
            {
                s_localStamp[4] -= 60;
                s_localStamp[3] += 1;
            }

            if (s_localStamp[3] > 23) // hour
            {
                s_localStamp[3] -= 24;
                s_localStamp[2] += 1; // day
            }
        }
    }
}


static char* s_formats[32] = {
        "/serial_data/%d%d%d_%d%d%d",
        "/serial_data/%d%d%d_%d%d0%d",
        "/serial_data/%d%d%d_%d0%d%d",
        "/serial_data/%d%d%d_%d0%d0%d",
        "/serial_data/%d%d%d_0%d%d%d",
        "/serial_data/%d%d%d_0%d%d0%d",
        "/serial_data/%d%d%d_0%d0%d%d",
        "/serial_data/%d%d%d_0%d0%d0%d",
        "/serial_data/%d%d0%d_%d%d%d",
        "/serial_data/%d%d0%d_%d%d0%d",
        "/serial_data/%d%d0%d_%d0%d%d",
        "/serial_data/%d%d0%d_%d0%d0%d",
        "/serial_data/%d%d0%d_0%d%d%d",
        "/serial_data/%d%d0%d_0%d%d0%d",
        "/serial_data/%d%d0%d_0%d0%d%d",
        "/serial_data/%d%d0%d_0%d0%d0%d",
        "/serial_data/%d0%d%d_%d%d%d",
        "/serial_data/%d0%d%d_%d%d0%d",
        "/serial_data/%d0%d%d_%d0%d%d",
        "/serial_data/%d0%d%d_%d0%d0%d",
        "/serial_data/%d0%d%d_0%d%d%d",
        "/serial_data/%d0%d%d_0%d%d0%d",
        "/serial_data/%d0%d%d_0%d0%d%d",
        "/serial_data/%d0%d%d_0%d0%d0%d",
        "/serial_data/%d0%d0%d_%d%d%d",
        "/serial_data/%d0%d0%d_%d%d0%d",
        "/serial_data/%d0%d0%d_%d0%d%d",
        "/serial_data/%d0%d0%d_%d0%d0%d",
        "/serial_data/%d0%d0%d_0%d%d%d",
        "/serial_data/%d0%d0%d_0%d%d0%d",
        "/serial_data/%d0%d0%d_0%d0%d%d",
        "/serial_data/%d0%d0%d_0%d0%d0%d"
};


static int s_fd = 0;


void setSDSave(int save)
{
    s_saveSD = save;
}

static void dataconverge_thread_entry(void *parameter)
{
    while (1)
    {
        rt_thread_mdelay(s_nPeriod);

        if (0==s_oldSaveSD  &&  1==s_saveSD)
        {
            s_oldSaveSD = 1;

            // create new file
            time_t now = time(RT_NULL);
            struct tm *p = localtime(&now);
            char strTime[32];
            int nFormatIndex = 16*(int)((1+p->tm_mon)<10)
            + 8*(int)((p->tm_mday)<10)
            + 4*(int)((p->tm_hour)<10)
            + 2*(int)((p->tm_min)<10)
            + (int)((p->tm_sec)<10);

            sprintf(strTime, s_formats[nFormatIndex],
                    (1900+p->tm_year),
                    (1+p->tm_mon),
                    p->tm_mday,
                    p->tm_hour,
                    p->tm_min,
                    p->tm_sec);

            s_fd = open(strTime, O_WRONLY | O_APPEND | O_CREAT);

            // set timestamp
        }

        if (1==s_oldSaveSD  &&  1==s_saveSD)
        {
            // save data to file
            rt_uint8_t tmp[1024] = {0};
            getTimeStamp(s_nPeriod);
            int nFrameLen = s_buf[2] + 256*s_buf[3];
            memcpy(tmp, s_localStamp, 7);
            memcpy(tmp+7, s_buf+4, nFrameLen);

            write(s_fd, tmp, nFrameLen+7);
            fsync(s_fd);
        }

        if (1==s_oldSaveSD  &&  0==s_saveSD)
        {
            s_oldSaveSD = 0;
            close(s_fd);
        }

        // send data to up
//        rt_uint8_t s_buf[1024] = {0};
        s_buf[0] = 0x7e;
        s_buf[1] = 0x7e;
        // s_buf[2-3] data len



        s_buf[4] = getRelayStatus();
        s_buf[5] = 0;

        copyAdc(s_buf+6);
        s_buf[22] = 0;
        s_buf[23] = 0;

        int nLenCom2 = 0;
        int nLenCom3 = 0;
        int nLenCom4 = 0;
        int nLenCom5 = 0;

        if (s_switch2)
        {
            nLenCom2 = copyData2(s_buf+24);
        }

        if (s_switch3)
        {
            nLenCom3 = copyData3(s_buf+24+nLenCom2);
        }

        if (s_switch4)
        {
            nLenCom4 = copyData4(s_buf+24+nLenCom2+nLenCom3);
        }

        if (s_switch5)
        {
            nLenCom5 = copyData5(s_buf+24+nLenCom2+nLenCom3+nLenCom4);
        }

        // data len
        int nFrameLen = 20+nLenCom2+nLenCom3+nLenCom4+nLenCom5;
        s_buf[2] = nFrameLen%256;
        s_buf[3] = nFrameLen/256;
        rt_uint8_t nSum = 0;
        for (int i=4; i<4+nFrameLen; ++i)
        {
            nSum += s_buf[i];
        }
        s_buf[4+nFrameLen] = nSum;

        rt_device_write(serial1, 0, s_buf, 5+nFrameLen);

    }
}



int DataConverge()
{
    rt_err_t ret = RT_EOK;

    cJSON* root = getComConfigRoot();
    cJSON* comInfo2 = cJSON_GetArrayItem(root, 1);
    s_switch2 = cJSON_GetObjectItem(comInfo2, "switchx")->valueint;

    cJSON* comInfo3 = cJSON_GetArrayItem(root, 2);
    s_switch3 = cJSON_GetObjectItem(comInfo3, "switchx")->valueint;

    cJSON* comInfo4 = cJSON_GetArrayItem(root, 3);
    s_switch4 = cJSON_GetObjectItem(comInfo4, "switchx")->valueint;

    cJSON* comInfo5 = cJSON_GetArrayItem(root, 4);
    s_switch5 = cJSON_GetObjectItem(comInfo5, "switchx")->valueint;

    cJSON* comInfo1 = cJSON_GetArrayItem(root, 0);
    s_nPeriod = cJSON_GetObjectItem(comInfo1, "period")->valueint;


    /* 创建 serial 线程 */
    rt_thread_t thread = rt_thread_create("tDCnvg", dataconverge_thread_entry, RT_NULL, 4096, 25, 10);
    /* 创建成功则启动线程 */
    if (thread != RT_NULL)
    {
        rt_kprintf("start tDataConverge thread ok\n");
        rt_thread_startup(thread);
    }
    else
    {
        rt_kprintf("start tDataConverge thread failed\n");
        ret = RT_ERROR;
    }


    return ret;
}


void restartDataConverge()
{
    cJSON* root = getComConfigRoot();
    cJSON* comInfo2 = cJSON_GetArrayItem(root, 1);
    s_switch2 = cJSON_GetObjectItem(comInfo2, "switchx")->valueint;

    cJSON* comInfo3 = cJSON_GetArrayItem(root, 2);
    s_switch3 = cJSON_GetObjectItem(comInfo3, "switchx")->valueint;

    cJSON* comInfo4 = cJSON_GetArrayItem(root, 3);
    s_switch4 = cJSON_GetObjectItem(comInfo4, "switchx")->valueint;

    cJSON* comInfo5 = cJSON_GetArrayItem(root, 4);
    s_switch5 = cJSON_GetObjectItem(comInfo5, "switchx")->valueint;

    cJSON* comInfo1 = cJSON_GetArrayItem(root, 0);
    s_nPeriod = cJSON_GetObjectItem(comInfo1, "period")->valueint;
}

